using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using OracleInternal.Json.Binary;
using OracleInternal.Json.Common;

namespace OracleInternal.Json.Sql
{
	internal class OracleJsonObject : OracleJsonStructure, IOracleJsonObject, IOracleJsonStructure, IOracleJsonValue, IDictionary<string, OracleJsonValue>, ICollection<KeyValuePair<string, OracleJsonValue>>, IEnumerable<KeyValuePair<string, OracleJsonValue>>, IEnumerable
	{
		internal Dictionary<string, OracleJsonValue> m_map = new Dictionary<string, OracleJsonValue>();

		public int Count => m_map.Count;

		public bool IsReadOnly => false;

		public OracleJsonValue this[string key]
		{
			get
			{
				if (m_map.ContainsKey(key))
				{
					return m_map[key];
				}
				return null;
			}
			set
			{
				m_map[key] = value;
			}
		}

		public ICollection<string> Keys => m_map.Keys;

		public ICollection<OracleJsonValue> Values => m_map.Values;

		internal OracleJsonObject()
		{
			m_map = new Dictionary<string, OracleJsonValue>();
		}

		internal OracleJsonObject(IOracleJsonObject other)
		{
			m_map = new Dictionary<string, OracleJsonValue>();
			foreach (KeyValuePair<string, OracleJsonValue> item in other)
			{
				string key = item.Key;
				OracleJsonValue value = item.Value;
				switch (value.GetOracleJsonType())
				{
				case OracleJsonType.OBJECT:
					m_map.Add(key, new OracleJsonObject(value.AsJsonObject()));
					break;
				case OracleJsonType.ARRAY:
					m_map.Add(key, new OracleJsonArray(value.AsJsonArray()));
					break;
				default:
					m_map.Add(key, value);
					break;
				}
			}
		}

		public void Add(KeyValuePair<string, OracleJsonValue> item)
		{
			m_map.Add(item.Key, item.Value);
		}

		public void Clear()
		{
			m_map.Clear();
		}

		public bool Contains(KeyValuePair<string, OracleJsonValue> item)
		{
			return m_map.ContainsKey(item.Key);
		}

		public void CopyTo(KeyValuePair<string, OracleJsonValue>[] array, int arrayIndex)
		{
			for (int i = arrayIndex; i < array.Length; i++)
			{
				m_map.Add(array[i].Key, array[i].Value);
			}
		}

		public bool Remove(KeyValuePair<string, OracleJsonValue> item)
		{
			return m_map.Remove(item.Key);
		}

		public bool Remove(string key)
		{
			return m_map.Remove(key);
		}

		public void Add(string key, OracleJsonValue value)
		{
			m_map.Add(key, value);
		}

		public bool ContainsKey(string key)
		{
			return m_map.ContainsKey(key);
		}

		public bool Remove1(string key)
		{
			return m_map.Remove(key);
		}

		public bool TryGetValue(string key, out OracleJsonValue value)
		{
			return m_map.TryGetValue(key, out value);
		}

		IEnumerator<KeyValuePair<string, OracleJsonValue>> IEnumerable<KeyValuePair<string, OracleJsonValue>>.GetEnumerator()
		{
			return m_map.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return m_map.GetEnumerator();
		}

		public override OracleJsonType GetOracleJsonType()
		{
			return OracleJsonType.OBJECT;
		}

		private void CheckNull(OracleJsonValue v)
		{
			if (v == null)
			{
				throw new NullReferenceException();
			}
		}

		internal int Size()
		{
			return m_map.Count;
		}

		internal bool IsEmpty()
		{
			return m_map.Count == 0;
		}

		internal OracleJsonValue Get(string key)
		{
			return m_map[key];
		}

		internal OracleJsonValue Put(string key, OracleJsonValue value)
		{
			CheckNull(value);
			m_map.Add(key, value);
			return value;
		}

		internal void PutAll(Dictionary<string, OracleJsonValue> m)
		{
			foreach (KeyValuePair<string, OracleJsonValue> item in m)
			{
				CheckNull(item.Value);
				m_map.Add(item.Key, item.Value);
			}
		}

		internal string GetJsonString(string name)
		{
			return m_map[name].AsJsonString().GetJsonString();
		}

		internal string GetJsonString(string name, string defaultValue)
		{
			OracleJsonValue oracleJsonValue = m_map[name];
			if (oracleJsonValue != null && oracleJsonValue.GetOracleJsonType() == OracleJsonType.STRING)
			{
				return oracleJsonValue.AsJsonString().GetJsonString();
			}
			return defaultValue;
		}

		internal int GetInt(string name)
		{
			return ((OracleJsonNumber)m_map[name]).IntValue();
		}

		internal int GetInt(string name, int defaultValue)
		{
			OracleJsonValue oracleJsonValue = m_map[name];
			if (!(oracleJsonValue is OracleJsonNumber))
			{
				return defaultValue;
			}
			return ((OracleJsonNumber)oracleJsonValue).IntValue();
		}

		internal double GetDouble(string name)
		{
			return ((OracleJsonNumber)m_map[name]).DoubleValue();
		}

		internal long GetLong(string key)
		{
			return ((OracleJsonNumber)m_map[key]).LongValue();
		}

		internal decimal GetBigDecimal(string key)
		{
			return ((OracleJsonNumber)m_map[key]).BigDecimalValue();
		}

		internal double GetDouble(string name, double defaultValue)
		{
			OracleJsonValue oracleJsonValue = m_map[name];
			if (!(oracleJsonValue is OracleJsonNumber))
			{
				return defaultValue;
			}
			return ((OracleJsonNumber)oracleJsonValue).DoubleValue();
		}

		internal long GetLong(string key, long defaultValue)
		{
			OracleJsonValue oracleJsonValue = m_map[key];
			if (!(oracleJsonValue is OracleJsonNumber))
			{
				return defaultValue;
			}
			return ((OracleJsonNumber)oracleJsonValue).LongValue();
		}

		internal decimal GetBigDecimal(string key, decimal defaultValue)
		{
			OracleJsonValue oracleJsonValue = m_map[key];
			if (!(oracleJsonValue is OracleJsonNumber))
			{
				return defaultValue;
			}
			return ((OracleJsonNumber)oracleJsonValue).BigDecimalValue();
		}

		internal bool GetBoolean(string name)
		{
			OracleJsonValue oracleJsonValue = m_map[name];
			if (oracleJsonValue == OracleJsonValue.TRUE)
			{
				return true;
			}
			if (oracleJsonValue == OracleJsonValue.FALSE)
			{
				return false;
			}
			throw new InvalidCastException();
		}

		internal bool GetBoolean(string name, bool defaultValue)
		{
			OracleJsonValue oracleJsonValue = m_map[name];
			if (oracleJsonValue == null)
			{
				return defaultValue;
			}
			if (oracleJsonValue == OracleJsonValue.TRUE)
			{
				return true;
			}
			if (oracleJsonValue == OracleJsonValue.FALSE)
			{
				return false;
			}
			return defaultValue;
		}

		internal bool IsNull(string name)
		{
			return m_map[name] == OracleJsonValue.NULL;
		}

		internal DateTime GetDateTime(string name)
		{
			OracleJsonValue oracleJsonValue = m_map[name];
			if (oracleJsonValue.GetOracleJsonType() == OracleJsonType.DATE)
			{
				return oracleJsonValue.AsJsonDate().GetDateTime();
			}
			return oracleJsonValue.AsJsonTimestamp().GetDateTime();
		}

		internal DateTime GetDateTime(string name, DateTime defaultValue)
		{
			OracleJsonValue oracleJsonValue = m_map[name];
			if (oracleJsonValue == null)
			{
				return defaultValue;
			}
			if (oracleJsonValue.GetOracleJsonType() == OracleJsonType.DATE)
			{
				return oracleJsonValue.AsJsonDate().GetDateTime();
			}
			if (oracleJsonValue.GetOracleJsonType() == OracleJsonType.TIMESTAMP)
			{
				return oracleJsonValue.AsJsonTimestamp().GetDateTime();
			}
			return defaultValue;
		}

		internal byte[] GetBytes(string name)
		{
			return Get(name).AsJsonBinary().GetBytes();
		}

		internal byte[] GetBytes(string name, byte[] defaultValue)
		{
			OracleJsonValue oracleJsonValue = m_map[name];
			if (oracleJsonValue == null)
			{
				return defaultValue;
			}
			if (oracleJsonValue.GetOracleJsonType() == OracleJsonType.BINARY)
			{
				return oracleJsonValue.AsJsonBinary().GetBytes();
			}
			return defaultValue;
		}

		internal OracleJsonValue Put(string name, byte[] value)
		{
			return Put(name, new OracleJsonBinary(value, isId: false));
		}

		internal OracleJsonValue Put(string name, string value)
		{
			return Put(name, new OracleJsonString(value.ToCharArray()));
		}

		internal OracleJsonValue Put(string name, int value)
		{
			return Put(name, new OracleJsonDecimal(value));
		}

		internal OracleJsonValue Put(string name, long value)
		{
			return Put(name, new OracleJsonDecimal(value));
		}

		internal OracleJsonValue Put(string name, decimal value)
		{
			return Put(name, new OracleJsonDecimal(value));
		}

		internal OracleJsonValue Put(string name, double value)
		{
			return Put(name, new OracleJsonDouble(value));
		}

		internal OracleJsonValue Put(string name, bool value)
		{
			return Put(name, value ? OracleJsonValue.TRUE : OracleJsonValue.FALSE);
		}

		internal OracleJsonValue PutNull(string name)
		{
			return Put(name, OracleJsonValue.NULL);
		}

		internal OracleJsonValue Put(string name, DateTime value)
		{
			return Put(name, new OracleJsonTimestamp(value));
		}

		public override string ToJsonString()
		{
			StringWriter stringWriter = new StringWriter();
			OracleJsonSerializer oracleJsonSerializer = new OracleJsonSerializer(stringWriter);
			oracleJsonSerializer.Write(this);
			oracleJsonSerializer.Close();
			return stringWriter.ToString();
		}
	}
}
